#include <QPixmap>
#include <QPainter>
#include <QMutexLocker>
#include <QFileInfo>
#include <QApplication>
#include <QDebug>

#include "processthread.h"

using namespace XVL;

ProcessThread::ProcessThread(SafeQueue* queue, QObject *parent)
    : AbstractThread(queue, parent)
{}

ProcessThread::~ProcessThread()
{}

XVL::XVImage* ProcessThread::imageToXVImage(QImage &image)
{
    // 创建XVImage对象
    XVImage* xvImage = new XVImage();
    xvImage->width = image.width();
    xvImage->height = image.height();
    xvImage->type = UInt8;

    // 转换为灰度图
    image = image.convertToFormat(QImage::Format_Grayscale8);
    xvImage->depth = 1;  // 灰度图通道数为1

    // 计算行间距（每行字节数）
    xvImage->pitch = image.bytesPerLine();

    // 分配数据内存并复制像素数据
    int totalBytes = xvImage->pitch * xvImage->height;
    xvImage->data = new BYTE[totalBytes];
    memcpy(xvImage->data, image.bits(), totalBytes);

    return xvImage;
}

bool ProcessThread::processImageData(XVL::XVImage *inputImage, vector<XVL::XVPath> &contours, vector<pair<int, int> > &periAndArea, vector<XVL::XVRegion>& filteredRegions)
{
    int res = 0;
    // 检查是否需要停止
    if (shouldStop())
    {
        return false;
    }

    // 1. 灰度阈值化
    XVThresholdImageToRegionMonoIn thresholdIn;
    thresholdIn.inImage = inputImage;
    thresholdIn.inMin = 0.0;     // 灰度最小值
    thresholdIn.inMax = 220.0;   // 灰度最大值
    XVThresholdImageToRegionMonoOut thresholdOut;
    res = XVThresholdImageToRegionMono(thresholdIn, thresholdOut);
    // 检查是否需要停止
    if (res != 0 || shouldStop())
    {
        return false;
    }

    // 获取灰度阈值化的输出区域
    XVRegion blackRegion = thresholdOut.outRegion;

    // 2. 填充
    XVFillRegionHolesIn fillIn;
    fillIn.inRegion = blackRegion;
    fillIn.inNeighborhood = 8;
    XVFillRegionHolesOut fillOut;
    res = XVFillRegionHoles(fillIn, fillOut);
    // 检查是否需要停止
    if (res != 0 || shouldStop())
    {
        return false;
    }

    // 3. 分割连通区域
    XVSplitRegionToBlobsIn splitIn;
    splitIn.inRegion = fillOut.outRegion;
    splitIn.inNeighborhood = 8;
    XVSplitRegionToBlobsOut splitOut;
    res = XVSplitRegionToBlobs(splitIn, splitOut);
    // 检查是否需要停止
    if (res != 0 || shouldStop())
    {
        return false;
    }

    // 获取所有独立区域
    vector<XVRegion> allRegions = splitOut.outRegions;
    // filteredRegions是过滤掉周长面积非常小的区域的vector
    filteredRegions.clear();
    filteredRegions.reserve(allRegions.size());

    // 4. 计算每个区域的轮廓、周长和面积
    contours.clear();
    periAndArea.clear();
    for (const auto& subRegion : allRegions)
    {
        // 检查是否需要停止
        if (shouldStop())
        {
            return false;
        }

        // 4.1 获取单个区域的轮廓
        XVRegionContoursIn contoursIn;
        contoursIn.inRegion = subRegion;
        contoursIn.inMode = XM_External;
        contoursIn.inMethod = XM_Center;
        contoursIn.inConnectivity = 8;
        XVRegionContoursOut contoursOut;
        res = XVRegionContours(contoursIn, contoursOut);

        // 4.2 计算单个区域的面积
        XVRegionAreaIn areaIn;
        areaIn.inRegion = subRegion;
        XVRegionAreaOut areaOut;
        res = XVRegionArea(areaIn, areaOut);
        int area = (res == 0) ? areaOut.outArea : 0;

        // 4.3 计算单个区域的周长
        XVRegionPerimeterIn perimeterIn;
        perimeterIn.inRegion = subRegion;
        XVRegionPerimeterOut perimeterOut;
        res = XVRegionPerimeter(perimeterIn, perimeterOut);
        int perimeter = (res == 0) ? static_cast<int>(perimeterOut.outPerimeter) : 0;
        // 排除调肉眼不可见的非常小的黑色区域
        if(perimeter < 20 || area < 20)
        {
            continue;
        }
        filteredRegions.emplace_back(subRegion);

        periAndArea.emplace_back(perimeter, area);
        // 保存外轮廓
        if (res == 0 && !contoursOut.outContours.empty())
        {
            contours.emplace_back(contoursOut.outContours[0]);
        }
    }
    return true;
}

QPixmap ProcessThread::drawContoursOnImage(const QImage &image, const vector<XVL::XVPath> &contours)
{
    QImage drawImage = image.copy();
    // 转化为Format_RGB32用于绘制轮廓
    drawImage = drawImage.convertToFormat(QImage::Format_RGB32);
    // 创建QPainter用于绘制
    QPainter painter(&drawImage);
    painter.setPen(QPen(Qt::blue, 2));
    // 遍历所有轮廓
    for (const auto& path : contours)
    {
        if (path.arrayPoint2D.empty()) continue;
        // 创建QPolygonF用于存储轮廓点
        QPolygonF polygon;
        // 预分配空间
        polygon.reserve(static_cast<int>(path.arrayPoint2D.size()));
        for (const auto& point : path.arrayPoint2D)
        {
            // 将XVPoint2D转换为QPointF
            polygon.append(QPointF(point.x, point.y));
        }
        // 绘制闭合轮廓
        painter.drawPolygon(polygon);
    }
    // 默认Label大小
    QSize targetSize(661, 168);
    // 按比例缩放图片适应目标大小
    return QPixmap::fromImage(drawImage).scaled(targetSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}

void ProcessThread::run()
{
    // 重置停止标志
    resetstopFlag();
    // 循环执行
    while (!shouldStop())
    {
        // 检查并等待暂停状态解除
        checkAndWaitRemovePause();
        // 从安全队列获取图片
        QImage image;
        if (!getQueue()->dequeue(image))
        {
            continue;
        }

        if(shouldStop())
        {
            break;
        }

        // QImage 转换为 XVImage
        XVImage* xvImage = imageToXVImage(image);
        if (!xvImage)
        {
            emit errorOccurred("图像格式转换失败");
            continue;
        }

        if (shouldStop())
        {
            delete[] xvImage->data;
            delete xvImage;
            break;
        }

        vector<XVPath> contours;
        vector<pair<int, int>> periAndArea;
        vector<XVL::XVRegion> filteredRegions;
        contours.reserve(15);
        periAndArea.reserve(15);

        // 计算周长、面积、轮廓，设置进输入参数中
        bool isSuccess = processImageData(xvImage, contours, periAndArea, filteredRegions);

        if (!isSuccess || shouldStop())
        {
            if (!shouldStop())
                emit errorOccurred("图像处理失败");
            continue;
        }

        // 绘制轮廓
        QPixmap processedImage = drawContoursOnImage(image, contours);

        if (shouldStop())
        {
            delete[] xvImage->data;
            delete xvImage;
            break;
        }

        // 构建处理结果结构体
        ProcessResult result;
        result.processedImage = processedImage;
        result.periAndArea = periAndArea;
        result.currentIndex = currentIndex_;
        currentIndex_++;
        if(currentIndex_ >= totalCount_)
        {
            resetProcessCount();
        }
        // 发送处理完成信号
        emit processedAndRegions(result, filteredRegions, xvImage->width);

        // 清理XVImage资源
        delete[] xvImage->data;
        delete xvImage;
        // 与加载线程都延时10ms
        msleep(10);
        // 第一次运行程序时，拿取一个图片就暂停
        if(isFirst_ || getManual())
        {
            pauseProcessing();
            if(isFirst_)
            {
                isFirst_ = false;
            }
            setManual(false);
        }
    }
}
